package com.srwl.mytx.widget;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.Vibrator;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.OverScroller;
import android.widget.RelativeLayout;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

/**
 * Created by dahai2070 on 2018/5/3 0003.
 */

public class MyScrollView extends RelativeLayout {
    static final int ANIMATED_SCROLL_GAP = 250;

    static final float MAX_SCROLL_FACTOR = 0.5f;


    private long mLastScroll;
    //滑动的左边界
    private int leftScrollBorder=0;
    //滑动的右边界
    private int rightScrollBorder;
    //滑动的上边界
    private int topScrollBorder=0;
    //滑动的下边界
    private int bottomScrollBorder;

    private boolean needToHandle;
    private boolean isMoving;


    private int mDownY;
    private int mDownX;
    private int moveX;
    private int moveY;
    /**
     * DragGridView自动滚动的速度
     */
    private static final int speed = 3;
    private View mStartDragItemView;
    private Handler mHandler = new Handler();
    private Vibrator mVibrator;
    private WindowManager.LayoutParams mWindowLayoutParams;
    /**
     * 我们拖拽的item对应的Bitmap
     */
    private Bitmap mDragBitmap;
    private int mPoint2ItemLeft;
    private int mOffset2Left;
    private int mPoint2ItemTop;
    private int mOffset2Top;
    private int mStatusHeight;
    private ImageView mDragImageView;
    private WindowManager mWindowManager;
    private long dragResponseMS = 500;
    private int mAutoScrollTopBorder;
    private int mAutoScrollLeftBorder;
    private int mAutoScrollBottomBorder;
    private int mAutoScrollRightBorder;
    private boolean isLongClick;
    //长按监听
    private MyListener myListener;
    private View targetView;
    //长按滑入某item标记
    private boolean isScrollIn = true;
    //长按滑出某item标记
    private boolean isScrollOut = false;
    private OverScroller mScroller;

    private boolean mIsBeingDragged = false;

    private VelocityTracker mVelocityTracker;

    private float mLastMotionY;
    private float mLastMotionX;
    private int mActivePointerId = INVALID_POINTER;

    private static final int INVALID_POINTER = -1;
    private boolean mFlingEnabled = true;
    private int mMinimumVelocity;
    private int mMaximumVelocity;


    public MyScrollView(@NonNull Context context) {
        super(context);
        init(context);
    }

    public MyScrollView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public MyScrollView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        final ViewConfiguration configuration = ViewConfiguration.get(getContext());
        mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
        mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();

        mScroller = new OverScroller(getContext());
        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);


        initAutoScrollBorder();
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mDownX = (int) ev.getX();
                mDownY = (int) ev.getY();
                mStartDragItemView = getPointView(mDownX, mDownY);
                //mStartDragItemView为空说明点击没在任何一个item上，视为拖动界面的操作，在onInterceptTouchEvent（）方法中拦截该事件，设置拦截标志mIsBeingDragged为true;
                if (mStartDragItemView == null) {
                    mIsBeingDragged = true;
                    break;
                }
                //mStartDragItemView不为空，说明点击在item上，视为对item的操作，在onInterceptTouchEvent（）方法中不拦截事件，让事件分发到item，故设置拦截标志mIsBeingDragged为false;
                mIsBeingDragged = false;
                mStartDragItemView.setVisibility(INVISIBLE);
                //使用Handler延迟dragResponseMS执行mLongClickRunnable
                mHandler.postDelayed(mLongClickRunnable, dragResponseMS);
                getPointOffsetofItem(mDownX, mDownY, mStartDragItemView);
                //手指点击处与点击view的上边缘和左边缘的距离
//                float y = mStartDragItemView.getY();
//                mPoint2ItemTop = (int) (mDownY- y);
//                mPoint2ItemLeft = (int) (mDownX- mStartDragItemView.getX());
                //HVScrollView与屏幕上边、左边的距离
                mOffset2Top = (int) (ev.getRawY() - mDownY);
                mOffset2Left = (int) (ev.getRawX() - mDownX);

                //开启mDragItemView绘图缓存
                mStartDragItemView.setDrawingCacheEnabled(true);
                //获取mDragItemView在缓存中的Bitmap对象
                mDragBitmap = Bitmap.createBitmap(mStartDragItemView.getDrawingCache());
                //这一步很关键，释放绘图缓存，避免出现重复的镜像
                mStartDragItemView.destroyDrawingCache();

                break;
            case MotionEvent.ACTION_MOVE:
                int moveX = (int) ev.getX();
                int moveY = (int) ev.getY();


                //滑动超过item的边界，移除前天添加到handler的mLongClickRunnable，长按时间不足1S，就中断长按事件的执行,且：如果长按事件已经激活，也没有必要再去remove了
                if (isPointOutItem(moveX, moveY, mStartDragItemView) && !isLongClick) {
                    mHandler.removeCallbacks(mLongClickRunnable);
                }
                break;

            case MotionEvent.ACTION_UP:
                mHandler.removeCallbacks(mLongClickRunnable);
                mHandler.removeCallbacks(mScrollRunnable);
                break;
        }

        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        final int action = ev.getAction();
//        if ((action == MotionEvent.ACTION_MOVE) && (mIsBeingDragged)) {
//            return true;
//        }

        switch (action & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN: {
//                final float x = ev.getX();
//                final float y = ev.getY();
//                if (!inChild((int) x, (int) y)) {
//                    mIsBeingDragged = false;
//                    break;
//                }
//
//
//                mLastMotionY = y;
//                mLastMotionX = x;
//                mActivePointerId = ev.getPointerId(0);
//                mIsBeingDragged = !mScroller.isFinished();

                //   mIsBeingDragged = true;
                break;
            }
            case MotionEvent.ACTION_MOVE: {

//                final int activePointerId = mActivePointerId;
//                if (activePointerId == INVALID_POINTER) {
//                    // If we don't have a valid id, the touch down wasn't on content.
//                    break;
//                }
//
//                final int pointerIndex = ev.findPointerIndex(activePointerId);
//                final float y = ev.getY(pointerIndex);
//                final int yDiff = (int) Math.abs(y - mLastMotionY);
//                if (yDiff > mTouchSlop) {
//                    mIsBeingDragged = true;
//                    mLastMotionY = y;
//                }
//                final float x = ev.getX(pointerIndex);
//                final int xDiff = (int) Math.abs(x - mLastMotionX);
//                if (xDiff > mTouchSlop) {
//                    mIsBeingDragged = true;
//                    mLastMotionX = x;
//                }
                if (isLongClick) {
                    mIsBeingDragged = true;
                } else {
                    mIsBeingDragged = false;
                }
                break;
            }


            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:

                mIsBeingDragged = false;
                mActivePointerId = INVALID_POINTER;
                break;
            case MotionEvent.ACTION_POINTER_UP:
                onSecondaryPointerUp(ev);
                break;
        }

        return mIsBeingDragged;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        //long currentMultiTouchTime = System.currentTimeMillis();
//            if (currentMultiTouchTime - lastMultiTouchTime < 200) {
//                return false;
//            }
        if (event.getAction() == MotionEvent.ACTION_DOWN && event.getEdgeFlags() != 0) {
            // Don't handle edge touches immediately -- they may actually belong to one of our
            // descendants.
            return false;
        }

        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(event);

        final int action = event.getAction();

        switch (action & MotionEvent.ACTION_MASK) {
            //如果down事件返回 false,那么就没法拦截 move 、up等事件了
            case MotionEvent.ACTION_DOWN: {
                isMoving = false;
                final float x = event.getX();
                final float y = event.getY();
//                    if (!(mIsBeingDragged = inChild((int) x, (int) y))) {
//                        return false;
//                    }

                if (!mScroller.isFinished()) {
                    mScroller.abortAnimation();
                }

                mLastMotionY = y;
                mLastMotionX = x;
                mActivePointerId = event.getPointerId(0);
                break;
            }
            case MotionEvent.ACTION_MOVE:
                isMoving = true;
                moveX = (int) event.getX();
                moveY = (int) event.getY();
                if (isLongClick) {
                    onDragItem(moveX, moveY);
                }
                if (mIsBeingDragged && !isLongClick) {
                    // Scroll to follow the motion event
                    final int activePointerIndex = event.findPointerIndex(mActivePointerId);
                    final int deltaY = (int) (mLastMotionY - moveY);
                    mLastMotionY = moveY;

                    final int deltaX = (int) (mLastMotionX - moveX);
                    mLastMotionX = moveX;

                    scrollBy(deltaX, deltaY);

                }
                break;
            case MotionEvent.ACTION_UP:
                isMoving = false;
                int currentX = (int) event.getX();
                int currentY = (int) event.getY();


                if (mIsBeingDragged && !isLongClick) {
                    if (mFlingEnabled) {
//                            final VelocityTracker velocityTracker = mVelocityTracker;
//                            velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
                        mVelocityTracker.computeCurrentVelocity(1000);
                        int initialVelocitx = (int) mVelocityTracker.getXVelocity();
                        int initialVelocity = (int) mVelocityTracker.getYVelocity();
                        //                  int initialVelocitx = (int) velocityTracker.getXVelocity(mActivePointerId);
                        //                  int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);


                        if (Math.abs(initialVelocitx) > mMinimumVelocity || Math.abs(initialVelocity) > mMinimumVelocity) {
                            computeMove(currentX, currentY, -initialVelocitx, -initialVelocity);
                        } else {
                            //当手指抬起，如果滑出边界后，那就根据设置的边界回弹
                            if (mScroller.springBack(getScrollX(), getScrollY(), leftScrollBorder, rightScrollBorder, topScrollBorder, bottomScrollBorder)) {
                                postInvalidateOnAnimation();
                            }
                        }
                        //  computeMove(x, y, -initialVelocitx, -initialVelocity);


                    }

                    mActivePointerId = INVALID_POINTER;
                    mIsBeingDragged = false;

                    if (mVelocityTracker != null) {
                        mVelocityTracker.recycle();
                        mVelocityTracker = null;
                    }
                }
                if (isLongClick) {
                    onStopDrag(currentX, currentY);
                    isLongClick = false;

                }
                break;
            case MotionEvent.ACTION_CANCEL:
                isMoving = false;
                if (mIsBeingDragged && getChildCount() > 0) {
                    mActivePointerId = INVALID_POINTER;
                    mIsBeingDragged = false;
                    if (mVelocityTracker != null) {
                        mVelocityTracker.recycle();
                        mVelocityTracker = null;
                    }
                }
                break;
            case MotionEvent.ACTION_POINTER_UP:
                onSecondaryPointerUp(event);
                break;
        }
        return true;


    }


    private void onDragItem(int moveX, int moveY) {
        mWindowLayoutParams.x = moveX - mPoint2ItemLeft;
        mWindowLayoutParams.y = moveY - mPoint2ItemTop;
        mWindowManager.updateViewLayout(mDragImageView, mWindowLayoutParams); //更新镜像的位置
        // onSwapItem(moveX, moveY);
        mHandler.post(mScrollRunnable);
        View pointView = getPointView(moveX, moveY);
        if (pointView == mStartDragItemView) {
            return;
        }
        if (pointView != null && isScrollIn) {
            targetView = pointView;
            isScrollIn = false;
            isScrollOut = true;
            myListener.onDragInTargetItem(targetView);
        } else if (pointView == null && isScrollOut) {
            isScrollIn = true;
            isScrollOut = false;
            myListener.onDragOutTargetItem(targetView);
        }

        //父view自动滚动
    }

    /**
     * 当moveY的值大于向上滚动的边界值，触发GridView自动向上滚动
     * 当moveY的值小于向下滚动的边界值，触犯GridView自动向下滚动
     * 否则不进行滚动
     */
    private Runnable mScrollRunnable = new Runnable() {

        @Override
        public void run() {
            int deltaX;
            int deltaY;
            if (moveY < mAutoScrollTopBorder) {
                deltaY = -speed;
                mHandler.postDelayed(mScrollRunnable, 25);
            } else if (moveY > mAutoScrollBottomBorder) {
                deltaY = speed;
                mHandler.postDelayed(mScrollRunnable, 25);
            } else {
                deltaY = 0;
            }
            if (moveX < mAutoScrollLeftBorder) {
                deltaX = -speed;
                mHandler.postDelayed(mScrollRunnable, 25);
            } else if (moveX > mAutoScrollRightBorder) {
                deltaX = speed;
                mHandler.postDelayed(mScrollRunnable, 25);
            } else {
                deltaX = 0;
            }
            //当我们的手指到达GridView向上或者向下滚动的偏移量的时候，可能我们手指没有移动，但是DragGridView在自动的滚动
            //所以我们在这里调用下onSwapItem()方法来交换item
            // onSwapItem(moveX, moveY);
            int scrollX = getScrollX();
            int scrollY = getScrollY();
            if (scrollX + deltaX < 0 || scrollX + deltaX > rightScrollBorder) {
                deltaX = 0;
            }
            if (scrollY + deltaY < 0 || scrollY + deltaY > bottomScrollBorder) {
                deltaY = 0;
            }
            if (deltaX == 0 && deltaY == 0) {
                mHandler.removeCallbacks(mScrollRunnable);
            }
            smoothScrollBy(deltaX, deltaY);
            // smoothScrollTo();
        }
    };


    //用来处理是否为长按的Runnable
    private Runnable mLongClickRunnable = new Runnable() {

        @Override
        public void run() {
            isLongClick = true; //设置可以拖拽
            //mIsBeingDragged=false;
            //  mVibrator.vibrate(50); //震动一下
            // mStartDragItemView.setVisibility(View.INVISIBLE);//隐藏该item

            //根据我们按下的点显示item镜像
            createDragImage(mDragBitmap, mDownX, mDownY);
        }
    };

    /**
     * 创建拖动的镜像
     *
     * @param bitmap
     * @param downX  按下的点相对父控件的X坐标
     * @param downY  按下的点相对父控件的X坐标
     */
    private void createDragImage(Bitmap bitmap, int downX, int downY) {
        mWindowLayoutParams = new WindowManager.LayoutParams();
        mWindowLayoutParams.format = PixelFormat.TRANSLUCENT; //图片之外的其他地方透明
        mWindowLayoutParams.gravity = Gravity.TOP | Gravity.LEFT;
        mWindowLayoutParams.x = downX - mPoint2ItemLeft;
        mWindowLayoutParams.y = downY - mPoint2ItemTop;
        mWindowLayoutParams.alpha = 0.55f; //透明度
        mWindowLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        mWindowLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        mWindowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;

        mDragImageView = new ImageView(getContext());
        mDragImageView.setImageBitmap(bitmap);
        mWindowManager.addView(mDragImageView, mWindowLayoutParams);
    }

    private View getPointView(int mDownX, int mDownY) {
        // RelativeLayout containerView = (RelativeLayout) getChildAt(0);
        for (int i = 0; i < getChildCount(); i++) {
            View childView = getChildAt(i);
            if (isPointOutItem(mDownX, mDownY, childView)) continue;
            return childView;
        }

        return null;
    }

    private boolean isPointOutItem(int mDownX, int mDownY, View childView) {
        if (childView == null) {
            return false;
        }
        int[] location = new int[2];
        childView.getLocationOnScreen(location);
        int x = location[0];
        int y = location[1];
        if (mDownX < x || mDownX > (x + childView.getWidth()) || mDownY < y || mDownY > (y + childView.getHeight())) {
            return true;
        }
        return false;
    }

    private void getPointOffsetofItem(int mDownX, int mDownY, View childView) {
        int[] location = new int[2];
        childView.getLocationOnScreen(location);
        int x = location[0];
        int y = location[1];
        mPoint2ItemTop = mDownY - y;
        mPoint2ItemLeft = mDownX - x;
    }

    /**
     * 停止拖拽我们将之前隐藏的item显示出来，并将镜像移除
     */
    private void onStopDrag(int x, int y) {
        // TODO: 2018/5/5 0005  判断up的位置是否落在某个item上方，如果是 调用接口提示数据更改
        View pointView = getPointView(x, y);
        if (pointView != null && pointView != mStartDragItemView && myListener != null) {
            myListener.onLongClickEnd(pointView, mStartDragItemView);
        }
        if (mStartDragItemView != null) {
            mStartDragItemView.setVisibility(View.VISIBLE);
        }

        removeDragImage();
    }

    /**
     * 从界面上面移动拖动镜像
     */
    private void removeDragImage() {
        if (mDragImageView != null) {
            mWindowManager.removeView(mDragImageView);
            mDragImageView = null;
        }
    }

    public void setOnLongClickListener(MyListener myListener) {
        this.myListener = myListener;

    }


    public void smoothScrollBy(int dx, int dy) {
        if (getChildCount() == 0) {
            // Nothing to do.
            return;
        }
        long duration = AnimationUtils.currentAnimationTimeMillis() - mLastScroll;
        if (duration > ANIMATED_SCROLL_GAP) {
            final int height = getHeight() - getPaddingBottom() - getPaddingTop();
            final int bottom = getChildAt(0).getHeight();
            final int maxY = Math.max(0, bottom - height);
            final int scrollY = getScrollY();
            dy = Math.max(0, Math.min(scrollY + dy, maxY)) - scrollY;

            final int width = getWidth() - getPaddingRight() - getPaddingLeft();
            final int right = getChildAt(0).getWidth();
            final int maxX = Math.max(0, right - width);
            final int scrollX = getScrollX();
            dx = Math.max(0, Math.min(scrollX + dx, maxX)) - scrollX;

            mScroller.startScroll(scrollX, scrollY, dx, dy);
            invalidate();
        } else {
            if (!mScroller.isFinished()) {
                mScroller.abortAnimation();
            }
            scrollBy(dx, dy);
        }
        mLastScroll = AnimationUtils.currentAnimationTimeMillis();
    }

    private boolean inChild(int x, int y) {
        if (getChildCount() > 0) {
            final int scrollX = getScrollX();
            final int scrollY = getScrollY();
            final View child = getChildAt(0);
            return !(y < child.getTop() - scrollY
                    || y >= child.getBottom() - scrollY
                    || x < child.getLeft() - scrollX
                    || x >= child.getRight() - scrollX);
        }
        return false;
    }

    private void onSecondaryPointerUp(MotionEvent ev) {
        final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >>
                MotionEvent.ACTION_POINTER_ID_SHIFT;
        final int pointerId = ev.getPointerId(pointerIndex);
        if (pointerId == mActivePointerId) {
            // This was our active pointer going up. Choose a new
            // active pointer and adjust accordingly.
            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
            mLastMotionX = ev.getX(newPointerIndex);
            mLastMotionY = ev.getY(newPointerIndex);
            mActivePointerId = ev.getPointerId(newPointerIndex);
            if (mVelocityTracker != null) {
                mVelocityTracker.clear();
            }
        }
    }

    public void computeMove(int startX, int startY, int velocityX, int velocityY) {
        int right = getChildAt(0).getWidth();
        int bottom = getChildAt(0).getHeight();
        mScroller.fling(getScrollX(), getScrollY(), velocityX, velocityY,
                leftScrollBorder, Math.max(0, rightScrollBorder),
                topScrollBorder, Math.max(0, bottomScrollBorder), right / 10, bottom / 8);//overX,over允许溢出边界的距离，也是回弹的距离
        postInvalidateOnAnimation();

    }

    public final void smoothScrollTo(int x, int y) {
        //根据移动的位置，确定视图能滑动的上下左右边界
        ViewGroup.LayoutParams layoutParams = this.getLayoutParams();
       int deltaX1;
       int deltaY1;
        if (x > 0) {
            deltaX1=x-rightScrollBorder;
            layoutParams.width=getWidth()+deltaX1;
            rightScrollBorder = x;
        } else if (x < 0) {
           deltaX1=x-leftScrollBorder;
           layoutParams.width=getWidth()-deltaX1;
            leftScrollBorder = x;
        }
        if (y > 0) {
            deltaY1=y-bottomScrollBorder;
            layoutParams.height=getHeight()+deltaY1;
            bottomScrollBorder = y;
        } else if (y < 0) {
            deltaY1=y-topScrollBorder;
            layoutParams.height=getHeight()-deltaY1;
            topScrollBorder = y;
        }

      //  this.setLayoutParams(layoutParams);


        if (!mScroller.isFinished()) {
            return;
        }
        int scrollX = getScrollX();
        int scrollY = getScrollY();
        int deltaX = x - scrollX;
        int deltaY = y - scrollY;


        mScroller.startScroll(scrollX, scrollY, deltaX, deltaY, 1000);
        invalidate();
    }

    @Override
    public void scrollTo(int x, int y) {
        if (x != getScrollX() || y != getScrollY()) {
            super.scrollTo(x, y);
        }
    }

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            // This is called at drawing time by ViewGroup.  We don't want to
            // re-show the scrollbars at this point, which scrollTo will do,
            // so we replicate most of scrollTo here.
            //
            //         It's a little odd to call onScrollChanged from inside the drawing.
            //
            //         It is, except when you remember that computeScroll() is used to
            //         animate scrolling. So unless we want to defer the onScrollChanged()
            //         until the end of the animated scrolling, we don't really have a
            //         choice here.
            //
            //         I agree.  The alternative, which I think would be worse, is to post
            //         something and tell the subclasses later.  This is bad because there
            //         will be a window where mScrollX/Y is different from what the app
            //         thinks it is.
            //
            int x = mScroller.getCurrX();
            int y = mScroller.getCurrY();
            super.scrollTo(x, y);
//            if (getChildCount() > 0) {
//                View child = getChildAt(0);
//                x = clamp(x, getWidth() - getPaddingRight() - getPaddingLeft(), child.getWidth());
//                y = clamp(y, getHeight() - getPaddingBottom() - getPaddingTop(), child.getHeight());
//                super.scrollTo(x, y);
//            }
            awakenScrollBars();


            postInvalidate();
        } else if (!isMoving) {
//            if (isNeedScrollBack()) {
//                postInvalidate();
//            }
//            mScroller.springBack(getScrollX(),getScrollY(),0,rightScrollBorder,0,bottomScrollBorder);
//            postInvalidateOnAnimation();
        }
    }

    private void initAutoScrollBorder() {
        //获取DragGridView自动向上滚动的偏移量，小于这个值，DragGridView向下滚动
        mAutoScrollBottomBorder = getHeight() * 3 / 4;
        //获取DragGridView自动向下滚动的偏移量，大于这个值，DragGridView向上滚动
        mAutoScrollTopBorder = getHeight() / 4;
        mAutoScrollLeftBorder = getWidth() / 4;
        mAutoScrollRightBorder = getWidth() * 3 / 4;
    }

    public interface MyListener {
        void onLongClickEnd(View targetView, View dragView);

        /**
         * 长按滑动过程中，滑进某个item的上方
         *
         * @param view
         */
        void onDragInTargetItem(View view);

        /**
         * 长按滑动过程中，滑出某个item的上方
         *
         * @param view
         */
        void onDragOutTargetItem(View view);

        void onScale(float scale);
    }
}
